﻿using System.Collections.Generic;
using System.Text;
using RayDen.Library.Core;
using RayDen.Library.Core.Primitives;
using RayDen.Library.Data.Imaging;

namespace RayDen.SmallPT
{
    public class PathTracerRenderer : MCPathIntegrator
    {
        public class PathInfo
        {
            public RayInfo PathRay;
            public Sample Sample;
            public PathVertex[] Vertices;
            public RgbSpectrum ThroughtPut;
        }

        protected int populationSize = 16384;
        protected List<PathInfo> paths;

        public override void Setup(Library.Entity.Interface.IRayDenLibraryFrame newFrame)
        {
            base.Setup(newFrame);
            paths = new List<PathInfo>(populationSize);
            InitializePaths();
        }

        public void InitializePaths()
        {
            for (int i = 0; i < populationSize; i++)
            {
                paths.Add(GetNewPath());
            }
        }

        public void AdvancePaths(FilmFrame fframe)
        {
            for (int i = 0; i < populationSize; i++)
            {
                var pathRadiance = EvaluatePath(paths[i].Vertices);
                var offset = (int)(Width * paths[i].Sample.ImageY + paths[i].Sample.ImageX);
                fframe.Data[offset] += pathRadiance;
                fframe.Weight[offset] += 1f;
            }
        }

        protected PathInfo GetNewPath()
        {
            var sample = sampler.GetNextSample(this.rnd.Value);
            IRay ray;
            this.camera.GetRay(sample.ImageX, sample.ImageY, out ray);
            return new PathInfo()
                {
                    Sample = sample,
                    PathRay = (RayInfo)ray,
                    Vertices = PropagatePath((RayInfo)ray, MaxRecursionLevel)
                };
        }
    }
}
